package com.athena.framework.proxy;

import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.athena.framework.annotation.AnnotationParsing;
import com.athena.framework.annotation.Aop;
import com.athena.framework.beanfactory.BeanFactory;
import com.athena.framework.beanfactory.DefaultBeanFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * @author likun
 * 2018/6/25 13:35
 **/
public class ProxyInit implements AnnotationParsing {

    private final static Logger logger = LoggerFactory.getLogger(AnnotationParsing.class);

    private BeanFactory beanFactory=DefaultBeanFactory.creatBeanFactory();

    @Override
    public void parsing() {
        if (logger.isInfoEnabled()){
            logger.info("开始设置aop代理...");
        }
        //获取含有Aop注解的类
        Set<Class<?>> classSet = findAllScanPackgeByAnnotation(Aop.class);
        cereteAop(classSet);
        //匹配需要的类型和方法并设置代理
        proxy(classSet);

        if (logger.isInfoEnabled()){
            logger.info("aop代理设置完成.");
        }
    }

    private void proxy(Set<Class<?>> classSet) {
        Set<String> keySet = beanFactory.getKeySet();
        for (Class<?> aopClass : classSet) {
            Aop aop = aopClass.getAnnotation(Aop.class);
            if (StrUtil.isNotBlank(aop.className()) && StrUtil.isNotBlank(aop.methodName())){
                for (String key : keySet) {
                    Object bean = beanFactory.getBean(key);
                    //类名匹配
                    if (ReUtil.isMatch(aop.className(),bean.getClass().getName())){
                        //获取bean的所有方法
                        Method[] methods = bean.getClass().getMethods();
                        List<Method> methodList=new ArrayList<>();
                        //获取所有匹配的方法
                        for (Method method : methods) {
                            String methodName = method.getName();
                            if (ReUtil.isMatch(aop.methodName(),methodName)){
                                methodList.add(method);
                            }
                        }
                        if (methodList.size()>0){
                            ProxyFactory proxyFactory = new ProxyFactory(bean,
                                    methodList,
                                    (ProxyInterface) beanFactory.getBean(aopClass));
                            Object instance = proxyFactory.getProxyInstance();
                            beanFactory.setBean(key,instance);
                        }
                    }
                }
            }
        }
    }

    /**
     * 实例化aop类并托管
     * @param classSet
     */
    private void cereteAop(Set<Class<?>> classSet) {
        Iterator<Class<?>> iterator = classSet.iterator();
        while (iterator.hasNext()){
            Class<?> aopClass = iterator.next();
            if (ProxyInterface.class.isAssignableFrom(aopClass)){
                try {
                    Object obj = aopClass.newInstance();
                    beanFactory.addBean(obj);
                } catch (InstantiationException e) {
                    logger.error("初始化异常:"+aopClass.getName(),e);
                } catch (IllegalAccessException e) {
                    logger.error("初始化参数错误:"+aopClass.getName(),e);
                }
            }else {
                if (logger.isWarnEnabled()){
                    logger.warn("{}没有实现接口{},已被抛弃!",aopClass.getName(),ProxyInterface.class.getName());
                }
                iterator.remove();
            }
        }
    }
}
